﻿using System;
using System.Runtime.InteropServices;
using System.Drawing;
using System.IO;

namespace EwbDesigner.NET.Classes
{
    /// <summary>
    /// Summary description for ShellIcon.
    /// </summary>
    /// <summary>
    /// Summary description for ShellIcon.  Get a small or large Icon with an easy C# function call
    /// that returns a 32x32 or 16x16 System.Drawing.Icon depending on which function you call
    /// either GetSmallIcon(string fileName) or GetLargeIcon(string fileName)
    /// </summary>
    public class ShellIcon
    {
        [StructLayout(LayoutKind.Sequential)]
        public struct SHFILEINFO
        {
            public IntPtr hIcon;
            public IntPtr iIcon;
            public uint dwAttributes;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
            public string szDisplayName;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 80)]
            public string szTypeName;
        };


        class Win32
        {
            public const uint SHGFI_LARGEICON = 0x000000000;        // 'Large icon
            public const uint SHGFI_SMALLICON = 0x000000001;        // 'Small icon
            public const uint SHGFI_OPENICON = 0x000000002;
            public const uint SHGFI_SHELLICONSIZE = 0x000000004;
            public const uint SHGFI_PIDL = 0x000000008;

            public const uint SHGFI_USEFILEATTRIBUTES = 0x000000010;
            public const uint SHGFI_ADDOVERLAYS = 0x000000020;
            public const uint SHGFI_OVERLAYINDEX = 0x000000040;

            public const uint SHGFI_ICON = 0x000000100;
            public const uint SHGFI_TYPENAME = 0x000000400;
            public const uint SHGFI_ATTRIBUTES = 0x000000800;

            public const uint SHGFI_ICONLOCATION = 0x000001000;
            public const uint SHGFI_EXETYPE = 0x000002000;
            public const uint SHGFI_SYSICONINDEX = 0x000004000;
            public const uint SHGFI_LINKOVERLAY = 0x000008000;

            public const uint SHGFI_SELECTED = 0x000010000;
            public const uint SHGFI_ATTR_SPECIFIED = 0x000020000;

            public const uint FILE_ATTRIBUTE_NORMAL = 0x80;
            public const uint FILE_ATTRIBUTE_DIRECTORY = 0x10;

            [DllImport("shell32.dll")]
            public static extern IntPtr SHGetFileInfo(string pszPath, uint dwFileAttributes, ref SHFILEINFO psfi, uint cbSizeFileInfo, uint uFlags);
        }


        public ShellIcon()
        {
            //
            // TODO: Add constructor logic here
            //
        }

        public static Icon GetSmallDirectoryIcon()
        {
            IntPtr hImgSmall; //the handle to the system image list
            SHFILEINFO shinfo = new SHFILEINFO();

            hImgSmall = Win32.SHGetFileInfo(Path.GetTempPath(), Win32.FILE_ATTRIBUTE_DIRECTORY, ref shinfo, (uint)Marshal.SizeOf(shinfo), Win32.SHGFI_ICON | Win32.SHGFI_SMALLICON);

            //The icon is returned in the hIcon member of the shinfo struct
            return System.Drawing.Icon.FromHandle(shinfo.hIcon);
        }

        public static Icon GetSmallIcon(string fileName)
        {
            IntPtr hImgSmall; //the handle to the system image list
            SHFILEINFO shinfo = new SHFILEINFO();

            //Use this to get the small Icon. 
            //If we do not have an actual physical file we need the FILE_ATTRIBUTE_NORMAL & SHGFI_USEFILEATTRIBUTES.
            if (File.Exists(fileName))
            {
                hImgSmall = Win32.SHGetFileInfo(fileName, 0, ref shinfo, (uint)Marshal.SizeOf(shinfo), Win32.SHGFI_ICON | Win32.SHGFI_SMALLICON);
            }
            else
            {
                hImgSmall = Win32.SHGetFileInfo(fileName, Win32.FILE_ATTRIBUTE_NORMAL, ref shinfo, (uint)Marshal.SizeOf(shinfo), Win32.SHGFI_ICON | Win32.SHGFI_SMALLICON | Win32.SHGFI_USEFILEATTRIBUTES);
            }

            //The icon is returned in the hIcon member of the shinfo struct
            return System.Drawing.Icon.FromHandle(shinfo.hIcon);
        }

        public static Icon GetLargeDirectoryIcon()
        {
            IntPtr hImgSmall; //the handle to the system image list
            SHFILEINFO shinfo = new SHFILEINFO();

            hImgSmall = Win32.SHGetFileInfo(@"\", Win32.FILE_ATTRIBUTE_DIRECTORY, ref shinfo, (uint)Marshal.SizeOf(shinfo), Win32.SHGFI_ICON | Win32.SHGFI_LARGEICON | Win32.SHGFI_USEFILEATTRIBUTES);

            //The icon is returned in the hIcon member of the shinfo struct
            return System.Drawing.Icon.FromHandle(shinfo.hIcon);
        }

        public static Icon GetLargeIcon(string fileName)
        {
            IntPtr hImgLarge; //the handle to the system image list
            SHFILEINFO shinfo = new SHFILEINFO();
            
            //Use this to get the large Icon
            hImgLarge = Win32.SHGetFileInfo(fileName, 0, ref shinfo, (uint)Marshal.SizeOf(shinfo), Win32.SHGFI_ICON | Win32.SHGFI_LARGEICON);

            //The icon is returned in the hIcon member of the shinfo struct
            return System.Drawing.Icon.FromHandle(shinfo.hIcon);
        }
    }
}

